package com.heima.comment.service.impl;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.heima.api.user.IUserClient;
import com.heima.comment.mapper.ApCommentMapper;
import com.heima.comment.mapper.ApCommentSensitiveMapper;
import com.heima.comment.service.ApCommentService;
import com.heima.common.aliyun.GreenTextScan;
import com.heima.model.comment.dtos.*;
import com.heima.model.comment.pojos.ApComment;
import com.heima.model.comment.pojos.ApCommentVo;
import com.heima.model.comment.pojos.CommentLike;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.user.pojos.ApUser;
import com.heima.model.wemedia.pojos.WmSensitive;
import com.heima.utils.common.CommentThreadLocalUtil;
import com.heima.utils.common.SensitiveWordUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.bson.types.ObjectId;
import org.springframework.beans.BeanUtils;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author tp
 * @description 针对表【ap_comment】的数据库操作Service实现
 * @createDate 2024-11-26 17:20:40
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class ApCommentServiceImpl extends ServiceImpl<ApCommentMapper, ApComment>
        implements ApCommentService {

    private final IUserClient userClient;
    private final ApCommentSensitiveMapper apCommentSensitiveMapper;
    private final GreenTextScan greenTextScan;
    private final MongoTemplate mongoTemplate;

    /**
     * 保存评论
     *
     * @param dto
     * @return
     */
    @Override
    public ResponseResult saveOne(CommentSaveDto dto) {
        Integer id = CommentThreadLocalUtil.getUser().getId();
        if (id == null) {
            return ResponseResult.errorResult(401, "用户未登录");
        }
        ApUser user = new ApUser();
        user.setId(id);
        user = userClient.queryUser(user);
        String content = dto.getContent();
        if (content == null || content.isEmpty()) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }
        int length = StringUtils.length(content);
        if (length > 140) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID, "评论内容过长");
        }
        //自定义敏感词审核
        boolean flag = handleSensitive(content);
        if (!flag) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID, "评论内容包含敏感词");
        }
        //文本审核
        flag = scanText(content);
        if (!flag) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID, "评论内容包含违规内容");
        }
        //插入数据库
        ApComment apComment = new ApComment();
        apComment.setAuthorId(user.getId());
        apComment.setAuthorName(user.getName());
        apComment.setEntryId(String.valueOf(dto.getArticleId()));
        apComment.setContent(dto.getContent());
        apComment.setFlag(0);
        apComment.setLikes(0);
        apComment.setReply(0);
        apComment.setType(0);
        long currentTimeMillis = System.currentTimeMillis();
        apComment.setCreatedTime(currentTimeMillis);
        apComment.setUpdatedTime(currentTimeMillis);
        mongoTemplate.save(apComment);
        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }

    /**
     * 评论列表查询
     *
     * @param dto
     * @return
     */
    @Override
    public ResponseResult load(CommentDto dto) {
        Query query = Query.query(Criteria.where("entryId").is(String.valueOf(dto.getArticleId())))
                .addCriteria(Criteria.where("flag").is(0))
                .addCriteria(Criteria.where("type").is(0))
                .addCriteria(Criteria.where("updatedTime").lte(dto.getMinDate().getTime()))
                .with(Sort.by(Sort.Direction.DESC, "createdTime"))
                .skip((long) dto.getSize() * (dto.getIndex() - 1))
                .limit(dto.getSize());
        List<ApCommentVo> apCommentVos = getApCommentVos(query);
        log.info("查询评论列表：{}", apCommentVos);
        return ResponseResult.okResult(apCommentVos);
    }

    /**
     * 点赞
     *
     * @param dto
     * @return
     */
    @Override
    public ResponseResult like(CommentLikeDto dto) {
        try {
            Integer userId = CommentThreadLocalUtil.getUser().getId();
            CommentLike commentLike = new CommentLike();
            commentLike.setEntryId(dto.getCommentId());
            commentLike.setUserId(userId);
            commentLike.setOperation(Integer.valueOf(dto.getOperation()));
            commentLike.setCreatedTime(System.currentTimeMillis());
            Query query = Query.query(Criteria.where("entryId").is(dto.getCommentId()))
                    .addCriteria(Criteria.where("userId").is(userId));
            List<CommentLike> commentLikes = mongoTemplate.find(query, CommentLike.class);
            if (CollectionUtils.isEmpty(commentLikes)) {
                mongoTemplate.save(commentLike);
            } else {
                mongoTemplate.updateFirst(Query.query(Criteria.where("id").is(commentLikes.get(0).getId())), Update.update("operation", dto.getOperation()), CommentLike.class);
            }
            // 根据 commentId 查询 MongoDB 中的评论
            ApComment comment = mongoTemplate.findById(dto.getCommentId(), ApComment.class);
            comment.setLikes(commentLike.getOperation() == 0 ? comment.getLikes() + 1 : comment.getLikes() - 1);
            mongoTemplate.updateFirst(Query.query(Criteria.where("id").is(dto.getCommentId())), Update.update("likes", comment.getLikes()), ApComment.class);
        } catch (Exception e) {
            log.error("评论点赞失败", e);
            return ResponseResult.errorResult(AppHttpCodeEnum.SERVER_ERROR);
        }
        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }

    /**
     * 回复评论
     *
     * @param dto
     * @return
     */
    @Override
    public ResponseResult repaySave(CommentRepaySaveDto dto) {
        Integer id = CommentThreadLocalUtil.getUser().getId();
        if (id == null) {
            return ResponseResult.errorResult(401, "用户未登录");
        }
        ApUser user = new ApUser();
        user.setId(id);
        user = userClient.queryUser(user);
        String content = dto.getContent();
        if (content == null || content.isEmpty()) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }
        int length = StringUtils.length(content);
        if (length > 140) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID, "评论内容过长");
        }
        //自定义敏感词审核
        boolean flag = handleSensitive(content);
        if (!flag) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID, "评论内容包含敏感词");
        }
        //文本审核
        flag = scanText(content);
        if (!flag) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID, "评论内容包含违规内容");
        }
        //插入数据库
        ApComment apComment = new ApComment();
        apComment.setAuthorId(user.getId());
        apComment.setAuthorName(user.getName());
        apComment.setEntryId(dto.getCommentId());
        apComment.setContent(dto.getContent());
        apComment.setFlag(0);
        apComment.setLikes(0);
        apComment.setReply(0);
        apComment.setType(1);
        long currentTimeMillis = System.currentTimeMillis();
        apComment.setCreatedTime(currentTimeMillis);
        apComment.setUpdatedTime(currentTimeMillis);
        mongoTemplate.save(apComment);
        ApComment comment = mongoTemplate.findById(apComment.getEntryId(), ApComment.class);
        Integer reply = comment.getReply() + 1;
        comment.setReply(reply);
        mongoTemplate.updateFirst(Query.query(Criteria.where("id").is(comment.getId())), Update.update("reply", comment.getReply()), ApComment.class);
        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }

    /**
     * 回复评论列表查询
     *
     * @param dto
     * @return
     */
    @Override
    public ResponseResult repayLoad(CommentRepayDto dto) {
        if (dto.getSize() == null){
            dto.setSize(10);
        }
        Query query = Query.query(Criteria.where("entryId").is(dto.getCommentId()))
                .addCriteria(Criteria.where("flag").is(0))
                .addCriteria(Criteria.where("type").is(1))
                .addCriteria(Criteria.where("createdTime").lte(dto.getMinDate().getTime()))
                .with(Sort.by(Sort.Direction.DESC, "createdTime"))
                .limit(dto.getSize());
        List<ApCommentVo> apCommentVos = getApCommentVos(query);
        log.info("查询回复评论列表：{}", apCommentVos);
        return ResponseResult.okResult(apCommentVos);
    }

    /**
     * 回复评论点赞
     *
     * @param dto
     * @return
     */
    @Override
    public ResponseResult repayLike(CommentRepayLikeDto dto) {
        try {
            Integer userId = CommentThreadLocalUtil.getUser().getId();
            CommentLike commentLike = new CommentLike();
            commentLike.setEntryId(dto.getCommentRepayId());
            commentLike.setUserId(userId);
            commentLike.setOperation(Integer.valueOf(dto.getOperation()));
            commentLike.setCreatedTime(System.currentTimeMillis());
            Query query = Query.query(Criteria.where("entryId").is(dto.getCommentRepayId()))
                    .addCriteria(Criteria.where("userId").is(userId));
            List<CommentLike> commentLikes = mongoTemplate.find(query, CommentLike.class);
            if (CollectionUtils.isEmpty(commentLikes)) {
                mongoTemplate.save(commentLike);
            } else {
                mongoTemplate.updateFirst(Query.query(Criteria.where("id").is(commentLikes.get(0).getId())), Update.update("operation", dto.getOperation()), CommentLike.class);
            }
            ApComment comment = mongoTemplate.findById(dto.getCommentRepayId(), ApComment.class);
            comment.setLikes(commentLike.getOperation() == 0 ? comment.getLikes() + 1 : comment.getLikes() - 1);
            mongoTemplate.updateFirst(Query.query(Criteria.where("id").is(dto.getCommentRepayId())), Update.update("likes", comment.getLikes()), ApComment.class);
        } catch (Exception e) {
            log.error("评论点赞失败", e);
            return ResponseResult.errorResult(AppHttpCodeEnum.SERVER_ERROR);
        }
        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }

    /**
     * 查询评论列表方法
     *
     * @param query
     * @return
     */
    private List<ApCommentVo> getApCommentVos(Query query) {
        List<ApComment> apComments = mongoTemplate.find(query, ApComment.class);
        List<ApCommentVo> apCommentVos = new ArrayList<>();
        apComments.forEach(apComment -> {
            ApCommentVo apCommentVo = new ApCommentVo();
            BeanUtils.copyProperties(apComment, apCommentVo);
            Query queried = Query.query(Criteria.where("entryId").is(apComment.getId()))
                    .addCriteria(Criteria.where("UserId").is(CommentThreadLocalUtil.getUser().getId()));
            List<CommentLike> commentLikes = mongoTemplate.find(queried, CommentLike.class);
            if (CollectionUtils.isEmpty(commentLikes)) {
                apCommentVo.setOperation(null);
            } else {
                apCommentVo.setOperation(commentLikes.get(0).getOperation());
            }
            apCommentVos.add(apCommentVo);
        });
        return apCommentVos;
    }

    /***
     * 自定义敏感词审核
     * @param content
     * @return
     */
    private boolean handleSensitive(String content) {
        boolean flag = true;
        //查询所有敏感词
        List<WmSensitive> wmSensitives = apCommentSensitiveMapper.selectList(Wrappers.emptyWrapper());
        if (CollectionUtils.isEmpty(wmSensitives)) {
            log.info("未定义敏感词，不做审核");
            return flag;
        }
        List<String> sensitiveWords = wmSensitives.stream().map(WmSensitive::getSensitives).collect(Collectors.toList());
        SensitiveWordUtil.initMap(sensitiveWords);
        Map<String, Integer> resultMap = SensitiveWordUtil.matchWords(content);
        if (!CollectionUtils.isEmpty(resultMap)) {
            flag = false;
        }

        return flag;
    }

    /**
     * 文本审核
     *
     * @param content
     * @return
     */
    private boolean scanText(String content) {
        boolean flag = true;
        try {
            Map result = greenTextScan.greeTextScan(content);
            log.info("文本审核结果：{}", result);
            flag = dealResult(result);
        } catch (Exception e) {
            log.error("文本扫描失败", e);
            return false;
        }
        return flag;
    }

    /**
     * 结果处理
     *
     * @param result
     * @return
     */
    private boolean dealResult(Map result) {
        boolean flag = true;
        if (result == null) {
            return flag;
        }
        String suggestion = result.get("suggestion") + "";
//        String label = result.get("label") + "";
        if ("pass".equals(suggestion)) {
            return flag;
        }
        //处理失败和人工
        flag = false;
        return flag;
    }
}




